/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Administrador;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import structure5.ComparableAssociation;
import structure5.Edge;
import structure5.GraphMatrixDirected;
import structure5.Map;

/**
 * Usted es el encargado de logística de una empresa de distribución de productos a tiendas en toda 
 * la República de Guatemala. Para apoyo de sus labores usted mantiene un grafo (con dirección), cuyos 
 * nodos son las ciudades principales de Guatemala y los arcos son la distancia, expresada en KM, que 
 * existe entre un par de ciudades.
 * 
 * 1. Preguntar el nombre de la ciudad origen y ciudad destino. El programa mostrará el valor de la 
 * ruta más corta y los nombres de las ciudades intermedias por donde pasa esa ruta.
 * 2. Indicar el nombre de la ciudad que queda en el centro del grafo.
 * 3. Modificar el grafo indicando algunos de los siguientes datos: a)hay interrupción de tráfico 
 * entre un par de ciudades o b)se establece una conexión entre ciudad1 y ciudad2 con valor de x KM de distancia. Al fin de estas modificaciones se recalculan las rutas más cortas y el nuevo centro del grafo.
 * 4. Finalizar el programa.
 * @author Vinicio Gomez, Douglas Davila
 * @since 03 noviembre 2012
 */
public class LogisticaTransporte {


    /**
     * grafo principal
     */
    public static GraphMatrixDirected<String,Integer> rutas;

    /**
     * @param args the command line arguments
     * @throws IOException  
     */
    public static void main(String[] args) throws IOException {
        System.out.println("Universidad del Valle de Guatemala");
        System.out.println("Algoritmos y Estructuras de Datos");
        System.out.println("Vinicio Gomez");
        System.out.println("Douglas Davila");
        System.out.println("");
        System.out.println("Hoja de Trabajo 8");
        System.out.println("Grafos -Floyd-");
        System.out.println("");
        System.out.println(""); 
        
        rutas = leer_archivo(new File("files/Rutas.txt"));
        System.out.println("MATRIZ DE DISTANCIAS MAS CORTAS ENTRE CIUDAD Y CIUDAD");
        Floyd.imprimir_matriz(rutas);
        boolean flag=true;
        while (flag){
        switch (menu()) {
            case 1:
                menu_dijstra();
                break;
            case 2:
                menu_modificar();
                break;
            case 3:
                menu_borrar();
                break;
            case 4:
                menu_agregar();
                break;
            case 5:
                flag = false;
                break;
            }
        }
    }
    
    private static void viaje_recursivo(String ciudad,Map<String,ComparableAssociation<Integer,Edge<String,Integer>>> results ) {
        try{
            System.out.print(" -> " + results.get(ciudad).getValue().here());
            viaje_recursivo(results.get(ciudad).getValue().here(), results);    
        }
        catch (NullPointerException e){
        }
    }
    /**
     * @param file nombre del archivo que contiene la informacion.
     * @return  grafo analizado
     * @throws IOException
     */
    public static  GraphMatrixDirected<String,Integer> leer_archivo (File file) throws IOException {
        GraphMatrixDirected<String,Integer> rutas = new GraphMatrixDirected<String,Integer>(100);
        // Declaracion e inicializacion de variables.
        BufferedReader wordreader = null;      
        long starttime;
        long endtime;
        // Verificar que sea un archivo que existen
        if (file.isFile()) {
            // Leer archivo
            try {
                wordreader = new BufferedReader(new FileReader(file));
            } catch (Exception ex) {
                System.out.println("Error al leer!");
            }            
            String line = null;
            String[] wordParts;
            // leer el archivo que contiene las palabras y cargarlo al WordSet.
            System.out.println("Lectura del archivo "+ file.toString());
            starttime = System.currentTimeMillis();
            try {
                line = wordreader.readLine();
            } catch (IOException ex) {
                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
            }
            while (line != null) {
                wordParts = line.split("\\.");
                if (wordParts.length == 3) {
                    
                    String ciudad1 = wordParts[0].trim();
                    String ciudad2 = wordParts[1].trim();
                    int km = Integer.parseInt(wordParts[2].trim());
                    rutas.add(ciudad1);
                    rutas.add(ciudad2);
                    rutas.addEdge(ciudad1, ciudad2,km);
//                    System.out.println("Origen: "+ciudad1);
//                    System.out.println("Destino: "+ciudad2);
//                    System.out.println("Kilometros: "+km);
                }
                line = wordreader.readLine();
            }
            // se terminaron las lineas que leer
            wordreader.close();
            endtime = System.currentTimeMillis();
            System.out.println("Rutas cargadas en " + (endtime - starttime) + " ms.");
        } else {
            System.out.println("Archivo no encontrado");
        }
        return rutas;
    }

    private static int  menu() {
        System.out.println("");
        System.out.println("");
        System.out.println("Presione el numero para la opcion que desea realizar:");
        System.out.println("1. Indicar ruta mas corta de ciudad ´A´ hacia ciudad ´B´.");
        System.out.println("2. Modificar rutas.");
        System.out.println("3. Eliminar rutas.");
        System.out.println("4. Agregar rutas");
        System.out.println("5. Salir.");
       
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int valor = 0;
        boolean flag = true;
        while (flag) {
            try {
                String str = in.readLine();
                try {
                    valor = Integer.parseInt(str);
                    if (valor>0 && valor < 6){
                        flag = false;
                    }
                    else {
                        System.out.println("Dato incorrecto");
                    }
                } catch (NumberFormatException e) {
                    System.out.println("Dato incorrecto");
                    flag = true;
                }
            } catch (IOException ex) {
                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return valor;
    }
    
     private static void menu_dijstra() {
        System.out.println("Ingrese el nombre de la Ciudad origen");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        boolean flag = true;
        while (flag) {
            try {
                String str = in.readLine();
                try {
                   
                    if (rutas.contains(str)){
                        boolean flag2=true;
                        while (flag2){
                            System.out.println("Ingrese el nombre de la Ciudad destino");
                            try {
                                String str2 = in.readLine();
                                try {
                                    if (rutas.contains(str2)) {
                                        String startName = str2;
                                        String destino = str;
                                        Map<String, ComparableAssociation<Integer, Edge<String, Integer>>> results = Dijkstra.dijkstra(rutas, startName);
                                        try {
                                            System.out.println("Distancia mas corta: " + results.get(destino).getKey() + "km.");
                                            System.out.print(results.get(destino).getValue().there());
                                        } catch (NullPointerException e) {
                                            System.out.println("No hay forma de llegar desde "+str+" hasta "+str2);
                                        }
                                        viaje_recursivo(destino, results);
                                        System.out.println();
                                        flag = false;
                                        flag2 = false;
                                    } else {
                                        System.out.println("Ciudad incorrecta");
                                    }
                                } catch (NumberFormatException e) {
                                    System.out.println("Dato incorrecto");
                                    flag = true;
                                }
                            } catch (IOException ex) {
                                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                    else {
                        System.out.println("Ciudad incorrecta");
                    }
                } catch (NumberFormatException e) {
                    System.out.println("Dato incorrecto");
                    flag = true;
                }
            } catch (IOException ex) {
                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void menu_modificar() {
     System.out.println("Ingrese el nombre de la Ciudad origen");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        boolean flag = true;
        while (flag) {
            try {
                String str = in.readLine();
                try {
                    if (rutas.contains(str)){
                        boolean flag2=true;
                        while (flag2){
                            System.out.println("Ingrese el nombre de la Ciudad destino");
                            try {
                                String str2 = in.readLine();
                                try {
                                    if (rutas.contains(str2)) {
                                        System.out.println("Ingrese la nueva distancia");
                                        boolean flag3 = true;
                                        while (flag3){
                                            String str3 = in.readLine();
                                            try{
                                                int km_new = Integer.parseInt(str3);
                                                flag = flag2 = flag3 =false;
                                                
                                                rutas.removeEdge(str2, str);
                                                rutas.addEdge(str2, str, km_new);
                                                System.out.println();
                                                System.out.println("Actualizando datos...");
                                                System.out.println();
                                                Floyd.imprimir_matriz(rutas);
                                            }
                                            catch (NumberFormatException e){
                                                System.out.println("Dato incorrecto");
                                                flag = true;  
                                            }
                                        }
                                    }    
                                } catch (NumberFormatException e) {
                                    System.out.println("Dato incorrecto");
                                    flag = true;
                                }
                            } catch (IOException ex) {
                                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                    else {
                        System.out.println("Ciudad incorrecta");
                    }
                } catch (NumberFormatException e) {
                    System.out.println("Dato incorrecto");
                    flag = true;
                }
            } catch (IOException ex) {
                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void menu_borrar() {
        System.out.println("Ingrese el nombre de la Ciudad origen");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        boolean flag = true;
        while (flag) {
            try {
                String str = in.readLine();
                try {
                    if (rutas.contains(str)){
                        boolean flag2=true;
                        while (flag2){
                            System.out.println("Ingrese el nombre de la Ciudad destino");
                            try {
                                String str2 = in.readLine();
                                try {
                                    if (rutas.contains(str2)) {
                                                flag = flag2 = false;
                                                rutas.removeEdge(str2, str);
                                                System.out.println();
                                                System.out.println("Actualizando datos...");
                                                System.out.println();
                                                Floyd.imprimir_matriz(rutas);                                        
                                    }    
                                } catch (NumberFormatException e) {
                                    System.out.println("Dato incorrecto");
                                    flag = true;
                                }
                            } catch (IOException ex) {
                                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                    else {
                        System.out.println("Ciudad incorrecta");
                    }
                } catch (NumberFormatException e) {
                    System.out.println("Dato incorrecto");
                    flag = true;
                }
            } catch (IOException ex) {
                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void menu_agregar() {
        System.out.println("Ingrese el nombre de la Ciudad origen");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        boolean flag = true;
        while (flag) {
            try {
                String str = in.readLine();
                try {
                        boolean flag2=true;
                        while (flag2){
                            System.out.println("Ingrese el nombre de la Ciudad destino");
                            try {
                                String str2 = in.readLine();
                                try {
                                        System.out.println("Ingrese la distancia");
                                        boolean flag3 = true;
                                        while (flag3){
                                            String str3 = in.readLine();
                                            try{
                                                int km_new = Integer.parseInt(str3);
                                                flag = flag2 = flag3 =false;
                                                rutas.add(str);
                                                rutas.add(str2);
                                                rutas.addEdge(str2, str, km_new);
                                                System.out.println();
                                                System.out.println("Actualizando datos...");
                                                System.out.println();
                                                Floyd.imprimir_matriz(rutas);
                                            }
                                            catch (NumberFormatException e){
                                                System.out.println("Dato incorrecto");
                                                flag = true;  
                                            }
                                        }  
                                } catch (NumberFormatException e) {
                                    System.out.println("Dato incorrecto");
                                    flag = true;
                                }
                            } catch (IOException ex) {
                                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                } catch (NumberFormatException e) {
                    System.out.println("Dato incorrecto");
                    flag = true;
                }
            } catch (IOException ex) {
                Logger.getLogger(LogisticaTransporte.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}